#ifndef __GWAPPLICATION_H__
#define __GWAPPLICAITON_H__

#include "../util/gwcommon.h"
#include "gwcommandline.h"

/**
*@file       gwapplication.h
*@brief      application framework
*
*@author     graywind
*@version    1.0.0.0
*@data       2011/12/27
*/

///application stuff
namespace gwBedrockApp
{
        ///base class of application framework
        class gwApplication;
}

///application stuff
namespace gwBedrockApp
{
        ///base class of application framework
        class gwApplication
        {
        protected:
                ///@brief    whether opened
                bool                        m_bIsOpen;
                ///@brief    whether running
                bool                        m_bRunning;
                ///@brief    the return code when exit main()
                long                        m_lReturnCode;

                ///@brief    your company name
                std::string                      m_strCompanyName;
                ///@brief    your application name
                std::string                      m_strAppName;
                ///@brief    your application version
                std::string                      m_strAppVersion;
                ///@brief    command line arguments parsed through gwCommandLine object
                gwBedrockApp::gwCommandLine      m_commandLineArgs;

        protected:
                ///@brief    open application, can be override by user, do something initialize here
                ///retval    bool
                virtual    bool     Open();

                ///@brief    close application, can be override by user, destroy global object should be fine
                ///retval    void
                virtual    void       Close();

                ///@brief    application loop, can be override by user, implement their own application loop
                ///retval    void
                virtual    void       Run();

                ///@brief    set the return code
                ///param[in] code     set the return code
                ///retval
                void       SetReturnCode(long code);

        public:
                ///@brief    global instance
                static     gwApplication*   g_pApplication;
        public:
                ///@brief    constructor
                gwApplication();
                ///@brief    destructor
                virtual    ~gwApplication();

                ///@brief    entry point, can be override by user
                ///param[in] argc     cpp standard command line arguments
                ///param[in] argv     cpp standard command line arguments
                ///retval    int      return code when exit program
                virtual    int  Main(int argc, char** argv);


                ///@brief    set your company name
                ///param[in] strCompanyName    new value
                ///retval    void
                void       SetCompanyName(const std::string& strCompanyName);
                ///@brief    set your application name
                ///param[in] strAppName    new value
                ///retval    void
                void       SetApplicationName(const std::string& strAppName);
                ///@brief    set your application version
                ///param[in] strAppVersion    new value
                ///retval    void
                void       SetApplicationVersion(const std::string& strAppVersion);
                ///@brief    set gwCommandLine object value
                ///param[in] commandLineArgs    another gwCommandLine instance
                ///retval    void
                void       SetCommandLineArgs(const gwBedrockApp::gwCommandLine& commandLineArgs);

                ///@brief    get company name(read-only)
                ///retval    const std::string&
                const      std::string&                        GetCompanyName() const;
                ///@brief    get application name(read-only)
                ///retval    const std::string&
                const      std::string&                        GetApplicationName() const;
                ///@brief    get application version(read-only)
                ///retval    const std::string&
                const      std::string&                        GetApplicationVersion() const;
                ///@brief    get gwCommandLine object(read-only)
                ///retval    const gwCommandLine&
                const      gwBedrockApp::gwCommandLine&        GetCommandLineArgs() const;

                ///@brief    whether opened
                ///retval    bool
                bool     IsOpen()        const;
                ///@brief    whether running
                ///retval    bool
                bool     IsRunning()     const;
                ///@brief    get the current return code
                ///retval    long
                long     GetReturnCode() const;

                ///@brief    termiante application
                ///retval    void
                void       Terminate();
        };

        /***************************************************************************************************************************/
        inline
        bool
        gwApplication::IsOpen() const
        {
                return m_bIsOpen;
        }

        /***************************************************************************************************************************/
        inline
        bool
        gwApplication::IsRunning() const
        {
                return m_bRunning;
        }

        /***************************************************************************************************************************/
        inline
        long
        gwApplication::GetReturnCode() const
        {
                return m_lReturnCode;
        }

        /***************************************************************************************************************************/
        inline
        void
        gwApplication::Terminate()
        {
                m_bRunning = false;
        }

        /***************************************************************************************************************************/
        inline
        void
        gwApplication::SetReturnCode(long int code)
        {
                m_lReturnCode = code;
        }

        /***************************************************************************************************************************/
        inline
        void
        gwApplication::SetCompanyName(const std::string &strCompanyName)
        {
                m_strCompanyName = strCompanyName;
        }

        /***************************************************************************************************************************/
        inline
        void
        gwApplication::SetApplicationName(const std::string &strApplicationName)
        {
                m_strAppName = strApplicationName;
        }

        /***************************************************************************************************************************/
        inline
        void
        gwApplication::SetApplicationVersion(const std::string &strApplicationVersion)
        {
                m_strAppVersion = strApplicationVersion;
        }

        /***************************************************************************************************************************/
        inline
        void
        gwApplication::SetCommandLineArgs(const gwBedrockApp::gwCommandLine &commandLineArgs)
        {
                m_commandLineArgs = commandLineArgs;
        }

        /***************************************************************************************************************************/
        inline
        const std::string&
        gwApplication::GetCompanyName() const
        {
                return m_strCompanyName;
        }

        /***************************************************************************************************************************/
        inline
        const std::string&
        gwApplication::GetApplicationName() const
        {
                return m_strAppName;
        }

        /***************************************************************************************************************************/
        inline
        const std::string&
        gwApplication::GetApplicationVersion() const
        {
                return m_strAppVersion;
        }

        /***************************************************************************************************************************/
        inline
        const gwBedrockApp::gwCommandLine&
        gwApplication::GetCommandLineArgs() const
        {
                return m_commandLineArgs;
        }


        ///@brief      derive class must contains those two macros in the header file and the source file
        /***************************************************************************************************************************/
#define GW_DECLARE_APPLICATION \
public:\
        static bool                        m_bInitialize;\
public:\
        static bool Initialize();\
public:\
        static gwApplication* GetApp()\
        {\
                return g_pApplication;\
        }\
private:



#define GW_IMPLEMENT_APPLICATION(classname) \
    bool classname::Initialize() \
    {\
         classname::g_pApplication = gw_new(classname);\
         return true;\
    }\
    bool classname::m_bInitialize = classname::Initialize();

}
#endif
